22  零售超市销售额预测

22.1 引言销售预测的商业价值

零售超市销售预测: - 库存管理: 避免缺货或积压 - 人员安排: 高峰期增加人手 - 营销策略: 促销时机选择 - 财务规划: 现金流预测

22.2 数据准备与探索

列表 22.1
# 注:01_Walmart_Store_sales.csv数据文件本地没有,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
# 导入相关包
import pandas as pd
import numpy as np  # 导入NumPy数值计算库
import seaborn as sns  # 导入Seaborn可视化库
import matplotlib.pyplot as plt  # 导入Matplotlib绑图库
from sklearn.preprocessing import StandardScaler  # 导入Scikit-learn的StandardScaler模块
from sklearn.model_selection import train_test_split  # 导入Scikit-learn的train_test_split模块
from sklearn.linear_model import LinearRegression  # 导入Scikit-learn的LinearRegression模块
from sklearn.metrics import r2_score  # 导入Scikit-learn的r2_score模块
 
# 读取数据
df = pd.read_csv('01_Walmart_Store_sales.csv', parse_dates = True, infer_datetime_format = True)
 
# 整理数据
df.Date=pd.to_datetime(df.Date)
 
df['weekday'] = df.Date.dt.weekday  # 提取日期时间属性
df['month'] = df.Date.dt.month  # 提取日期时间属性
df['year'] = df.Date.dt.year  # 提取日期时间属性
# 删除日期、星期、年份等非特征列
df.drop(['Date','weekday','year'], axis=1, inplace=True)
target = 'Weekly_Sales'  # 指定目标变量为"Weekly_Sales"
 
# 相关性分析和特征选择
plt.figure(figsize=(10,8))
# 绑制变量两两关系图
sns.pairplot(df, x_vars=['Holiday_Flag', 'Temperature', 'Fuel_Price', 'CPI', 'Unemployment','month'],
            y_vars=['Weekly_Sales'], height=4, aspect=0.7, kind='reg')  # 定义列表y_vars
plt.savefig("1.png")  # 保存图形至文件
plt.show()  # 显示图形
 
df1=df.copy(deep=True)  # 深拷贝数据框用于独立分析(不影响原始数据)
df1.drop(['Store'], axis=1, inplace=True)  # 删除不需要的列'Store'
corr_matrix = df1.corr()  # 计算相关系数矩阵
plt.figure(figsize=(10,8))  # 创建图形画布
sns.heatmap(corr_matrix, annot=True, cmap='Reds')  # 绑制热力图
plt.savefig("2.png")  # 保存图形至文件
plt.show()  # 显示图形
 
df.drop(['Fuel_Price'], axis=1, inplace=True)  # 删除不需要的列'Fuel_Price'
# 分类数据处理
df = pd.get_dummies(df, columns=['Store','month'])
 
# 提取特征和标签
X = df.drop([target],axis=1)
y = df[target]  # 提取目标变量列赋值给y
 
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, test_size=0.2, random_state=100)

# 数据标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)  # 对数据进行变换
X_test = scaler.transform(X_test)  # 对数据进行变换
 
# 训练多元线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)  # 在数据上训练model模型
 
# 测试集预测
y_pred = model.predict(X_test)
r2 =  r2_score(y_test, y_pred)  # 计算R²评估模型拟合优度
# 评估模型预测效果
print('R平方值(R^2):', r2)

22.3 特征工程

列表 22.2
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目:特征工程与特征相关性分析
# =============================================================================
# 本代码进行特征工程,包括相关性分析和特征选择。通过可视化各特征
# 与目标变量的关系,识别重要特征并剔除冗余特征,提升模型性能和
# 可解释性。这是机器学习项目中至关重要的一步。

# ==================== 定义特征列表 ====================
# 选择可能影响销售额的特征变量
features = ['Holiday_Flag', 'Temperature', 'Fuel_Price', 'CPI', 'Unemployment', 'month']
# Holiday_Flag: 假期标志,假期销售通常更高
# Temperature: 温度,可能影响购物意愿
# Fuel_Price: 燃油价格,影响消费者的出行和购买力
# CPI: 消费价格指数,衡量通胀水平
# Unemployment: 失业率,反映经济状况
# month: 月份,捕捉季节性规律

# 定义目标变量(要预测的变量)
target = 'Weekly_Sales'  # 周销售额是本项目的预测目标

# ==================== 绘制散点图矩阵 ====================
# 使用Seaborn绘制散点图矩阵,展示各特征与目标变量的关系
sns.pairplot(
    df,  # 数据源DataFrame
    x_vars=features,  # x轴变量列表(所有特征)
    y_vars=[target],  # y轴变量列表(目标变量)
    height=4,  # 每个子图的高度(英寸)
    aspect=0.7,  # 子图的宽高比(宽度/高度)
    kind='reg'  # 绘制带回归线的散点图
)
plt.suptitle('各特征与销售额的关系', y=1.02)  # 设置总标题,y=1.02将标题向上移动避免重叠
plt.show()  # 显示散点图矩阵

# ==================== 计算相关性矩阵 ====================
# 创建数据副本,避免修改原始数据
df1 = df.copy(deep=True)  # deep=True创建深拷贝,包括数据和索引

# 删除Store列(分类变量,无法计算相关系数)
df1.drop(['Store'], axis=1, inplace=True)  # axis=1表示删除列,inplace=True直接在原数据上修改

# 计算所有数值变量的相关系数矩阵
corr_matrix = df1.corr()  # corr()方法计算皮尔逊相关系数,返回对称矩阵
# 相关系数范围[-1, 1],绝对值越大相关性越强

# ==================== 绘制相关性热力图 ====================
plt.figure(figsize=(10, 8))  # 创建画布,尺寸为10x8英寸

# 使用Seaborn绘制热力图,可视化相关系数矩阵
sns.heatmap(corr_matrix, annot=True, cmap='Reds', center=0)
# annot=True在每个格子中显示相关系数的数值
# cmap='Reds'使用红色系配色方案(颜色越深相关性越强)
# center=0将颜色映射的中心设为0(白色表示无相关)

plt.title('特征相关性热力图')  # 设置图表标题
plt.show()  # 显示热力图

# ==================== 特征选择 ====================
# 根据相关性分析结果,删除与目标变量相关性低的特征
df.drop(['Fuel_Price'], axis=1, inplace=True)  # 删除燃油价格列
# 如果Fuel_Price与Weekly_Sales的相关系数接近0,说明它对预测没有帮助
# 删除不相关特征可以降低模型复杂度,避免过拟合

# ==================== 输出解读 ====================
# 散点图矩阵展示了各特征与销售额的线性关系:
# - 如果点的分布近似直线,说明存在线性关系
# - 如果回归线斜率较大,说明该特征对销售额影响显著
# - 如果点很分散,说明该特征预测能力弱
#
# 热力图展示了所有特征之间的相关性:
# - 红色越深表示正相关越强
# - 蓝色越深表示负相关越强
# - 白色表示无相关
#
# 特征选择原则:
# 1. 删除与目标变量相关性低的特征
# 2. 删除与其他特征高度相关的特征(多重共线性)
# 3. 保留与目标变量相关性高的特征

22.4 模型构建

列表 22.3
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目:构建线性回归模型预测销售额
# =============================================================================
# 本代码完成机器学习建模的完整流程:数据预处理、特征编码、数据标准化、
# 模型训练和评估。线性回归是最基础的预测模型,假设特征与目标变量之间
# 存在线性关系,适合作为基准模型。

# ==================== 分类变量编码 ====================
# 将分类变量转换为虚拟变量(独热编码)
df = pd.get_dummies(df, columns=['Store', 'month'])
# pd.get_dummies将分类变量转换为0/1指示变量
# columns参数指定要编码的列
# 例如:Store列有45个不同商店,会生成45个新列(Store_1, Store_2, ..., Store_45)
# 每行只有一个Store列为1,其余为0

# ==================== 准备特征和标签 ====================
# 提取特征矩阵X(删除目标变量列)
X = df.drop([target], axis=1)  # axis=1表示删除列
# X是一个DataFrame,包含所有特征列

# 提取目标变量y(销售额)
y = df[target]  # y是一个Series,包含所有销售额值

# ==================== 划分训练集和测试集 ====================
# 将数据划分为训练集(80%)和测试集(20%)
X_train, X_test, y_train, y_test = train_test_split(
    X,  # 特征矩阵
    y,  # 目标变量
    train_size=0.8,  # 训练集占比80%
    test_size=0.2,  # 测试集占比20%
    random_state=100  # 随机种子,保证每次运行结果相同
)
# train_test_split随机打乱数据并按指定比例划分
# 返回四个数组:训练集特征、测试集特征、训练集标签、测试集标签

# ==================== 数据标准化 ====================
# 创建标准化器(将数据转换为均值为0、标准差为1的分布)
scaler = StandardScaler()  # StandardScaler使用z-score标准化: (x - mean) / std

# 在训练集上拟合标准化器,并转换训练集数据
X_train_scaled = scaler.fit_transform(X_train)  # fit计算均值和标准差,transform应用标准化

# 使用训练集的均值和标准差转换测试集数据
X_test_scaled = scaler.transform(X_test)  # 注意:测试集使用训练集的统计量,不重新计算
# 这样确保模型在测试时看到的数据分布与训练时一致

# ==================== 训练线性回归模型 ====================
# 创建线性回归模型对象
model = LinearRegression()  # LinearRegression实现了普通最小二乘法(OLS)

# 在训练数据上拟合模型
model.fit(X_train_scaled, y_train)  # fit方法学习特征与目标变量的线性关系
# 模型学习: y = w1*x1 + w2*x2 + ... + wn*xn + b
# 其中w是权重(系数),b是截距

# ==================== 模型预测 ====================
# 使用训练好的模型预测测试集的销售额
y_pred = model.predict(X_test_scaled)  # predict方法返回预测的销售额

# ==================== 模型评估 ====================
# 计算R²分数(决定系数),评估模型拟合优度
r2 = r2_score(y_test, y_pred)  # R²范围[0, 1],越接近1说明拟合越好
# R² = 1 - (残差平方和 / 总平方和)
# 表示模型解释的方差占总方差的比例

print(f"R²值: {r2:.4f}")  # 打印R²值,保留4位小数

# 将R²转换为百分比形式,更直观
print(f"模型解释了{r2*100:.1f}%的方差")  # 例如:0.85表示模型解释了85%的方差

# ==================== 输出解读 ====================
# 线性回归模型的评估指标解读:
# 1. R²值(决定系数):
#    - R² = 1: 完美拟合(所有点都在回归线上)
#    - R² = 0.8以上: 拟合良好
#    - R² = 0.5-0.8: 中等拟合
#    - R² < 0.5: 拟合较差
#    - R² = 0: 模型与简单猜测(用均值预测)一样差
#
# 2. 模型系数(model.coef_):
#    - 每个特征的权重表示该特征对销售额的影响程度
#    - 正系数:特征增加,销售额增加
#    - 负系数:特征增加,销售额减少
#    - 系数绝对值越大,影响越重要
#
# 3. 截距(model.intercept_):
#    - 当所有特征为0时的销售额(基准值)
#
# 4. 残差分析:
#    - 残差 = 真实值 - 预测值
#    - 理想情况下,残差应服从正态分布,均值为0
#    - 如果残差有模式,说明模型有改进空间
#
# 5. 实际应用:
#    - 超市可以根据预测结果提前备货
#    - 识别影响销售的关键因素
#    - 优化营销策略和人员安排